package net.whzjkj.gateway.tcpserver.processor;

import com.alibaba.fastjson.JSON;
import io.netty.buffer.Unpooled;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import lombok.extern.slf4j.Slf4j;
import net.whzjkj.gateway.core.codce.JT808MessageEncoder;
import net.whzjkj.gateway.core.session.Session;
import net.whzjkj.gateway.core.session.TCPSessionManager;
import net.whzjkj.gateway.model.vo.*;
import net.whzjkj.gateway.tcpserver.service.SenderService;

import javax.annotation.Resource;
import java.io.IOException;

/**
 * @description: 消息处理
 * @author: Mr.Hu
 * @create: 2018-11-01 09:42
 **/
@Slf4j
public abstract class AbstractMessageProcessor<T> implements TerminalMessageProcessor{

    @Resource
    private TCPSessionManager sessionManager;
    @Resource
    private JT808MessageEncoder messageEncoder;
    @Resource
    private SenderService senderService;
    /**
     * 发送消息
     * @param channel
     * @param msg
     * @throws InterruptedException
     */
    protected void sendMessage(Channel channel, byte[] msg) throws InterruptedException {
        ChannelFuture future = channel.writeAndFlush(Unpooled.copiedBuffer(msg)).sync();
        if (!future.isSuccess()) {
            log.error("发送数据出错:{}", future.cause());
        }
    }

    protected int getFlowNo(Channel channel, int defaultValue) {
        Session session = sessionManager.findBySessionId(Session.buildId(channel));
        if (session == null) {
            return defaultValue;
        }
        return session.currentFlowNo();
    }

    protected int getFlowNo(Channel channel) {
        return this.getFlowNo(channel, 0);
    }


    public void processRegisterMsg(TerminalRegisterMessageVO msg) throws Exception {
        log.debug("终端注册:{}", JSON.toJSONString(msg, true));

        final String sessionId = Session.buildId(msg.getChannel());
        Session session = sessionManager.findBySessionId(sessionId);
        if (session == null) {
            session = Session.buildSession(msg.getChannel(), msg.getMessageHeader().getTerminalPhone());
        }
        session.setAuthenticated(true);
        session.setTerminalPhone(msg.getMessageHeader().getTerminalPhone());
        sessionManager.put(session.getId(), session);

        TerminalRegisterMessageRespVO respMsgBody = new TerminalRegisterMessageRespVO();
        respMsgBody.setReplyCode(TerminalRegisterMessageRespVO.success);
        respMsgBody.setReplyFlowId(msg.getMessageHeader().getMessageFlowNo());
        // TODO 鉴权码暂时写死
        respMsgBody.setReplyToken("123");
        int flowId = getFlowNo(msg.getChannel());
        byte[] bs = messageEncoder.encode4TerminalRegisterResp(msg, respMsgBody, flowId);
        sendMessage(msg.getChannel(), bs);
    }

    public void processAuthMsg(TerminalAuthenticationMessageVO msg) throws Exception {
        // TODO 暂时每次鉴权都成功

        log.debug("终端鉴权:{}", JSON.toJSONString(msg, true));

        final String sessionId = Session.buildId(msg.getChannel());
        Session session = sessionManager.findBySessionId(sessionId);
        if (session == null) {
            session = Session.buildSession(msg.getChannel(), msg.getMessageHeader().getTerminalPhone());
        }
        session.setAuthenticated(true);
        session.setTerminalPhone(msg.getMessageHeader().getTerminalPhone());
        sessionManager.put(session.getId(), session);
        serverCommonRespond(msg);
    }

    public void processTerminalHeartBeatMsg(PackageData req) throws Exception {
        log.debug("心跳信息:{}", JSON.toJSONString(req, true));
        serverCommonRespond(req);
    }

    public void processTerminalLogoutMsg(PackageData req) throws Exception {
        log.info("终端注销:{}", JSON.toJSONString(req, true));
        serverCommonRespond(req);
    }

    /**
     * 平台通用应答
     * @param req
     * @throws InterruptedException
     */
    protected void serverCommonRespond(PackageData req) throws InterruptedException, IOException {
        ServerCommonRespVO respondBody = new ServerCommonRespVO();
        respondBody.setRespondFlowNo(req.getMessageHeader().getMessageFlowNo())
            .setRespondMessageId(req.getMessageHeader().getMessageId())
            .setRespondCode(ServerCommonRespVO.ServerCommonRespondBodyEnum.RESPONDCODE_SUCCESS.code);
        int flowNo = getFlowNo(req.getChannel());
        byte[] msg = JT808MessageEncoder.encoderServerCommonRespondMessage(req, respondBody, flowNo);
        sendMessage(req.getChannel(), msg);
    }

    /**
     * 发送消息到消息队列
     * @param t
     */
    protected void send2Queue(T t){
        senderService.send(t);
    }
}
